﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Telerik.Web.UI;
using Control = System.Web.UI.Control;
using ITemplate = System.Web.UI.ITemplate;
using Page = System.Web.UI.Page;
using System.Web.UI;

namespace Medianamik.UI.Controls
{
    public class NodeComboTree : RadComboBox
    {
        private readonly TreeViewTemplate _treeViewTemplate = new TreeViewTemplate();

        new public Unit Width { get; set; }
        new public Unit Height { get; set; }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            ItemTemplate = _treeViewTemplate;
            Items.Add(new RadComboBoxItem(""));
            base.Width = Width;
            DropDownWidth = base.Width;
            base.Height = Height;
            EnableLoadOnDemand = true;

        }

        public void SetSelectedNode(Guid pNodeId)
        {
            var treeNode = _treeViewTemplate.Tree.Nodes.FindNodeByValue(pNodeId.ToString());

            //Charger les noeuds nécessaires à la sélection de la valeur actuelle
            if (treeNode == null)
            {
                var node = NodeManager.GetNode(pNodeId);
                var parents = NodeManager.GetParentNodes(node, null, false, 0);
                parents.Sort((n1, n2) => n1.Depth.CompareTo(n2.Depth));
                var nodes = _treeViewTemplate.Tree.Nodes;

                foreach (var parent in parents)
                {
                    //Trouver le parent (le plus lointain) dans la liste des noeuds chargés
                    //et charger ses enfants
                    var parentNode = nodes.FindNodeByValue(parent.ID.ToString());

                    if (parentNode != null)
                    {
                        TreeViewTemplate.ExpandNode(parentNode);
                        nodes = parentNode.Nodes;
                    }
                }

                treeNode = nodes.FindNodeByValue(pNodeId.ToString());
                treeNode.Selected = true;
                Items[0].Text = treeNode.Text;
                Items[0].Value = treeNode.Value;
            }
            else
            {
                treeNode.Selected = true;
                Items[0].Text = treeNode.Text;
                Items[0].Value = treeNode.Value;
            }

            base.SelectedValue = pNodeId.ToString();
        }

        public override string SelectedValue
        {
            get
            {
                return Items[0].Value;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    base.SelectedValue = value;
                else
                    SetSelectedNode(new Guid(value));
            }
        }

        private class TreeViewTemplate : ITemplate
        {
            private readonly RadTreeView _tree = new RadTreeView();

            public void InstantiateIn(Control container)
            {
                var div = new HtmlGenericControl("div");
                div.Attributes.Add("onclick", "StopPropagation(event)");
                container.Controls.Add(div);
                div.Controls.Add(Tree);

                Tree.Nodes.AddRange(ConfigManager.GetAll<MedianamikModule>()
                .OrderBy(m => m.Position).Select(m => new RadTreeNode(m.DisplayName, m.ID.ToString())));

                foreach (RadTreeNode node in Tree.Nodes)
                {
                    node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
                }

                Tree.NodeExpand += NodeExpand;

                var specializedScriptName = "OnClientNodeClickingHandlerFor" + container.Parent.ClientID;

                Tree.OnClientNodeClicking = specializedScriptName;

                //Le script doit exister (différent) pour chaque instance de ComboTree
                var specializedScript = String.Concat("function " + specializedScriptName + "(sender, args) {\n",
                        " var comboBox = $find('" + container.Parent.ClientID + "');\n",
                        " var node = args.get_node();\n",
                        " var comboBoxItem = comboBox.get_items().getItem(0);\n",
                        "if (node.get_category() == \"Disabled\" || node.get_value() == comboBoxItem.get_value()) {\n",
                            "args.set_cancel(true);}\n",
                        "else {\n",
                            " comboBox.trackChanges();\n",
                            " comboBoxItem.set_value(node.get_value());\n",
                            " comboBox.set_text(node.get_text());\n",
                            " comboBox.commitChanges();\n",
                            " comboBox.hideDropDown();}\n",
                    "}\n");

                var genericScript = String.Concat("function StopPropagation(e) {\n",
                        "if(typeof(e) == 'undefined' || !e) {\n",
                            " e = window.event;}\n",
                        "e.cancelBubble = true;\n",
                    "}\n");

                ScriptManager.RegisterClientScriptBlock(container.Page, typeof(Page), specializedScriptName, specializedScript, true);
                ScriptManager.RegisterClientScriptBlock(container.Page, typeof(Page), "StopPropagation", genericScript, true);
            }

            private static void NodeExpand(object sender, RadTreeNodeEventArgs e)
            {
                ExpandNode(e.Node);
            }

            public static void ExpandNode(RadTreeNode node)
            {
                node.Expanded = true;

                var medNodes = NodeManager.GetChildNodes(new Guid(node.Value));

                foreach (var n in medNodes)
                {
                    var treeNode = new RadTreeNode(Utility.GetFriendlyIdentifier(n,
                        MedianamikContext.Current.CurrentUICulture.Name),
                               n.ID.ToString());

                    if (n.HasChildren)
                        treeNode.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;

                    node.Nodes.Add(treeNode);
                }
            }

            public RadTreeView Tree
            {
                get { return _tree; }
            }
        }
    }
}
